{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "([1, 0, 2, 1, 1], [1, 0, 1, 0, 0])"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import random\n",
    "import numpy as np\n",
    "\n",
    "\n",
    "#模拟生成数据的函数\n",
    "def get_O(T):\n",
    "    #这里是真实数据,也就是训练的目标\n",
    "    A = np.array([[0.5, 0.2, 0.3], [0.3, 0.5, 0.2], [0.2, 0.3, 0.5]])\n",
    "    B = np.array([[0.5, 0.5], [0.4, 0.6], [0.7, 0.3]])\n",
    "    pi = np.array([0.2, 0.4, 0.4])\n",
    "\n",
    "    #状态链\n",
    "    I = []\n",
    "\n",
    "    #输出链\n",
    "    O = []\n",
    "\n",
    "    #循环的次数就是输出链的长度\n",
    "    for i in range(T):\n",
    "\n",
    "        #状态转移的随机数\n",
    "        r = random.random()\n",
    "\n",
    "        #如果是第一次的话,用pi的概率确定第一个a\n",
    "        if i == 0:\n",
    "            a = pi\n",
    "\n",
    "        #否则,用上次a的概率求下一个a的概率\n",
    "        if r < a[0]:\n",
    "            idx = 0\n",
    "        elif r < a[0] + a[1]:\n",
    "            idx = 1\n",
    "        else:\n",
    "            idx = 2\n",
    "\n",
    "        a = A[idx]\n",
    "        b = B[idx]\n",
    "        I.append(idx)\n",
    "\n",
    "        #计算输出的随机数\n",
    "        r = random.random()\n",
    "\n",
    "        if r < b[0]:\n",
    "            O.append(0)\n",
    "        else:\n",
    "            O.append(1)\n",
    "\n",
    "    return I, O\n",
    "\n",
    "\n",
    "get_O(5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([[2., 2., 1., ..., 0., 0., 0.],\n",
       "        [0., 0., 1., ..., 0., 0., 0.],\n",
       "        [2., 1., 2., ..., 0., 0., 0.],\n",
       "        ...,\n",
       "        [1., 1., 1., ..., 2., 2., 2.],\n",
       "        [2., 2., 0., ..., 1., 1., 1.],\n",
       "        [2., 2., 1., ..., 1., 0., 0.]]), array([[0., 1., 0., ..., 0., 1., 1.],\n",
       "        [0., 1., 1., ..., 1., 0., 0.],\n",
       "        [0., 0., 0., ..., 1., 1., 0.],\n",
       "        ...,\n",
       "        [1., 0., 0., ..., 1., 1., 0.],\n",
       "        [0., 0., 0., ..., 1., 1., 1.],\n",
       "        [0., 0., 0., ..., 1., 1., 1.]]))"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "T = 1000\n",
    "\n",
    "#状态链\n",
    "I_s = np.empty((T, T))\n",
    "\n",
    "#输出链\n",
    "O_s = np.empty((T, T))\n",
    "\n",
    "for i in range(T):\n",
    "    I_s[i], O_s[i] = get_O(T)\n",
    "\n",
    "I_s, O_s"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([[0., 0., 0.],\n",
       "        [0., 0., 0.],\n",
       "        [0., 0., 0.]]), array([[0., 0.],\n",
       "        [0., 0.],\n",
       "        [0., 0.]]), array([0., 0., 0.]))"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#A是状态转换概率矩阵,标识不同状态之间相互转换的概率\n",
    "A = np.zeros((3, 3))\n",
    "\n",
    "#B是输出概率矩阵,标识在不同状态下各个输出的概率\n",
    "B = np.zeros((3, 2))\n",
    "\n",
    "#pi是第一次会进去某个状态的概率\n",
    "pi = np.zeros(3)\n",
    "\n",
    "A, B, pi"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0.181, 0.412, 0.407])"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#pi的概率直接拿I_s的第一列计算就行了\n",
    "pi[0] = np.sum([I_s[:, 0] == 0]) / T\n",
    "pi[1] = np.sum([I_s[:, 0] == 1]) / T\n",
    "pi[2] = np.sum([I_s[:, 0] == 2]) / T\n",
    "pi"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(331974, 165697, 65943, 100334)"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a_from_0_to_any = 0\n",
    "a_from_0_to_0 = 0\n",
    "a_from_0_to_1 = 0\n",
    "a_from_0_to_2 = 0\n",
    "\n",
    "a_from_1_to_any = 0\n",
    "a_from_1_to_0 = 0\n",
    "a_from_1_to_1 = 0\n",
    "a_from_1_to_2 = 0\n",
    "\n",
    "a_from_2_to_any = 0\n",
    "a_from_2_to_0 = 0\n",
    "a_from_2_to_1 = 0\n",
    "a_from_2_to_2 = 0\n",
    "\n",
    "#遍历所有的状态\n",
    "for i in range(T):\n",
    "    #最后一个状态不用看了,因为他不会转变成很别的状态\n",
    "    for j in range(T - 1):\n",
    "        a = I_s[i, j]\n",
    "\n",
    "        #处理当前状态是0的情况\n",
    "        if a == 0:\n",
    "            a_from_0_to_any += 1\n",
    "\n",
    "            #看下一个状态是谁,就给谁的转换次数+1就行了\n",
    "            a_next = I_s[i, j + 1]\n",
    "            if a_next == 0:\n",
    "                a_from_0_to_0 += 1\n",
    "            if a_next == 1:\n",
    "                a_from_0_to_1 += 1\n",
    "            if a_next == 2:\n",
    "                a_from_0_to_2 += 1\n",
    "\n",
    "        if a == 1:\n",
    "            a_from_1_to_any += 1\n",
    "            a_next = I_s[i, j + 1]\n",
    "            if a_next == 0:\n",
    "                a_from_1_to_0 += 1\n",
    "            if a_next == 1:\n",
    "                a_from_1_to_1 += 1\n",
    "            if a_next == 2:\n",
    "                a_from_1_to_2 += 1\n",
    "\n",
    "        if a == 2:\n",
    "            a_from_2_to_any += 1\n",
    "            a_next = I_s[i, j + 1]\n",
    "            if a_next == 0:\n",
    "                a_from_2_to_0 += 1\n",
    "            if a_next == 1:\n",
    "                a_from_2_to_1 += 1\n",
    "            if a_next == 2:\n",
    "                a_from_2_to_2 += 1\n",
    "\n",
    "a_from_0_to_any, a_from_0_to_0, a_from_0_to_1, a_from_0_to_2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0.49912644, 0.19863905, 0.30223451],\n",
       "       [0.29932175, 0.5013634 , 0.19931485],\n",
       "       [0.19979381, 0.30027362, 0.49993257]])"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#这里的工作就很简单了,以A[0,0]为例,A0转换到A0的概率,就是A0到A0的次数 / A0到任何状态的次数\n",
    "A[0][0] = a_from_0_to_0 / a_from_0_to_any\n",
    "A[0][1] = a_from_0_to_1 / a_from_0_to_any\n",
    "A[0][2] = a_from_0_to_2 / a_from_0_to_any\n",
    "\n",
    "A[1][0] = a_from_1_to_0 / a_from_1_to_any\n",
    "A[1][1] = a_from_1_to_1 / a_from_1_to_any\n",
    "A[1][2] = a_from_1_to_2 / a_from_1_to_any\n",
    "\n",
    "A[2][0] = a_from_2_to_0 / a_from_2_to_any\n",
    "A[2][1] = a_from_2_to_1 / a_from_2_to_any\n",
    "A[2][2] = a_from_2_to_2 / a_from_2_to_any\n",
    "\n",
    "A"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(332324, 166071, 166253)"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "b_0_out_any = 0\n",
    "b_0_out_0 = 0\n",
    "b_0_out_1 = 0\n",
    "\n",
    "b_1_out_any = 0\n",
    "b_1_out_0 = 0\n",
    "b_1_out_1 = 0\n",
    "\n",
    "b_2_out_any = 0\n",
    "b_2_out_0 = 0\n",
    "b_2_out_1 = 0\n",
    "\n",
    "#遍历所有的状态\n",
    "for i in range(T):\n",
    "    for j in range(T):\n",
    "        a = I_s[i, j]\n",
    "        b = O_s[i, j]\n",
    "\n",
    "        #处理当前状态是0的情况\n",
    "        if a == 0:\n",
    "            b_0_out_any += 1\n",
    "\n",
    "            #看b输出是谁,就给谁+1就行了\n",
    "            if b == 0:\n",
    "                b_0_out_0 += 1\n",
    "            if b == 1:\n",
    "                b_0_out_1 += 1\n",
    "\n",
    "        if a == 1:\n",
    "            b_1_out_any += 1\n",
    "\n",
    "            #看b输出是谁,就给谁+1就行了\n",
    "            if b == 0:\n",
    "                b_1_out_0 += 1\n",
    "            if b == 1:\n",
    "                b_1_out_1 += 1\n",
    "\n",
    "        if a == 2:\n",
    "            b_2_out_any += 1\n",
    "\n",
    "            #看b输出是谁,就给谁+1就行了\n",
    "            if b == 0:\n",
    "                b_2_out_0 += 1\n",
    "            if b == 1:\n",
    "                b_2_out_1 += 1\n",
    "\n",
    "b_0_out_any, b_0_out_0, b_0_out_1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0.49972617, 0.50027383],\n",
       "       [0.39972129, 0.60027871],\n",
       "       [0.70001138, 0.29998862]])"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#这里的工作就很简单了,以B[0,0]为例,B0输出0的概率,就是B0输出0的次数 / B0输出任何结果的次数\n",
    "B[0][0] = b_0_out_0 / b_0_out_any\n",
    "B[0][1] = b_0_out_1 / b_0_out_any\n",
    "\n",
    "B[1][0] = b_1_out_0 / b_1_out_any\n",
    "B[1][1] = b_1_out_1 / b_1_out_any\n",
    "\n",
    "B[2][0] = b_2_out_0 / b_2_out_any\n",
    "B[2][1] = b_2_out_1 / b_2_out_any\n",
    "\n",
    "B"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
